package websocket

import (
	"common/global"
	"context"
	"equipment_server/model"
	"log"
	"net/http"

	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/bson/primitive"
	"go.mongodb.org/mongo-driver/mongo/options"
)

// ServeWs handles websocket requests from the peer.
func ServeWs(hub *Hub, w http.ResponseWriter, r *http.Request) {
	// Authenticate the user
	// We'll expect a token in the query string, e.g., /ws?token=...
	token := r.URL.Query().Get("token")
	userID, err := Authenticate(token) // This function needs to be implemented
	if err != nil {
		http.Error(w, "Unauthorized", http.StatusUnauthorized)
		return
	}

	conn, err := upgrader.Upgrade(w, r, nil)
	if err != nil {
		log.Println(err)
		return
	}
	client := &Client{hub: hub, conn: conn, send: make(chan []byte, 256), UserID: userID}
	client.hub.register <- client

	// Allow collection of memory referenced by the caller by doing all work in
	// new goroutines.
	go client.writePump()
	go client.readPump()

	// Send offline messages after client is registered
	go sendOfflineMessages(userID)
}

func sendOfflineMessages(userID uint) {
	collection := global.MonGoDatabase.Collection("offline_ws_messages")
	ctx := context.TODO()

	// Find messages for the user
	filter := bson.M{"user_id": userID}
	opts := options.Find().SetSort(bson.D{{"timestamp", 1}}) // oldest first
	cursor, err := collection.Find(ctx, filter, opts)
	if err != nil {
		log.Printf("Failed to find offline messages for user %d: %v", userID, err)
		return
	}
	defer cursor.Close(ctx)

	var messagesToDelete []primitive.ObjectID
	for cursor.Next(ctx) {
		var msg model.OfflineWsMessage
		if err := cursor.Decode(&msg); err != nil {
			log.Printf("Failed to decode offline message for user %d: %v", userID, err)
			continue
		}

		// Send message to user
		GlobalHub.mu.RLock()
		client, ok := GlobalHub.clients[userID]
		GlobalHub.mu.RUnlock()

		if ok {
			client.send <- msg.Message
			messagesToDelete = append(messagesToDelete, msg.ID)
		}
	}

	// Delete sent messages
	if len(messagesToDelete) > 0 {
		deleteFilter := bson.M{"_id": bson.M{"$in": messagesToDelete}}
		_, err := collection.DeleteMany(ctx, deleteFilter)
		if err != nil {
			log.Printf("Failed to delete offline messages for user %d: %v", userID, err)
		} else {
			log.Printf("Deleted %d offline messages for user %d", len(messagesToDelete), userID)
		}
	} else {
		log.Printf("No offline messages for user %d", userID)
	}
}
